package org.mybatis.generator.api.plus;

import java.util.List;
import java.util.Properties;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;

/**
 * @author wangfupeng
 */
public class MybatisPluginSerializable extends PluginAdapter {

    private FullyQualifiedJavaType serializable;

    public MybatisPluginSerializable() {
        this.serializable = new FullyQualifiedJavaType("java.io.Serializable");
    }

    public boolean validate(List<String> warnings) {
        return true;
    }

    public void setProperties(Properties properties) {
        super.setProperties(properties);
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        makeSerializable(topLevelClass, introspectedTable);
        return true;
    }

    @Override
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        makeSerializable(topLevelClass, introspectedTable);
        return true;
    }

    @Override
    public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass,
                                                      IntrospectedTable introspectedTable) {
        makeSerializable(topLevelClass, introspectedTable);
        return true;
    }

    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        topLevelClass.addImportedType(this.serializable);
        topLevelClass.addSuperInterface(this.serializable);
        Field field = new Field();
        field.setFinal(true);
        field.setInitializationString("1L");
        field.setName("serialVersionUID");
        field.setStatic(true);
        field.setType(new FullyQualifiedJavaType("long"));
        field.setVisibility(JavaVisibility.PRIVATE);
        this.context.getCommentGenerator().addFieldComment(field, introspectedTable);
        topLevelClass.addField(field);
        for (InnerClass innerClass : topLevelClass.getInnerClasses()) {
            if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) {
                innerClass.addSuperInterface(this.serializable);
                addInnerClassField(innerClass, introspectedTable);
            }
            if ("Criteria".equals(innerClass.getType().getShortName())) {
                innerClass.addSuperInterface(this.serializable);
                addInnerClassField(innerClass, introspectedTable);
            }
            if ("Criterion".equals(innerClass.getType().getShortName())) {
                innerClass.addSuperInterface(this.serializable);
                addInnerClassField(innerClass, introspectedTable);
            }
        }
        return true;
    }

    protected void makeSerializable(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        topLevelClass.addImportedType(this.serializable);
        topLevelClass.addSuperInterface(this.serializable);
        addTopLevelClassField(topLevelClass, introspectedTable);
    }

    protected void addTopLevelClassField(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        Field fieldInnerClass = new Field();
        fieldInnerClass.setFinal(true);
        fieldInnerClass.setInitializationString("1L");
        fieldInnerClass.setName("serialVersionUID");
        fieldInnerClass.setStatic(true);
        fieldInnerClass.setType(new FullyQualifiedJavaType("long"));
        fieldInnerClass.setVisibility(JavaVisibility.PRIVATE);
        this.context.getCommentGenerator().addFieldComment(fieldInnerClass, introspectedTable);
        topLevelClass.addField(fieldInnerClass);
    }

    protected void addInnerClassField(InnerClass innerClass, IntrospectedTable introspectedTable) {
        Field fieldInnerClass = new Field();
        fieldInnerClass.setFinal(true);
        fieldInnerClass.setInitializationString("1L");
        fieldInnerClass.setName("serialVersionUID");
        fieldInnerClass.setStatic(true);
        fieldInnerClass.setType(new FullyQualifiedJavaType("long"));
        fieldInnerClass.setVisibility(JavaVisibility.PRIVATE);
        this.context.getCommentGenerator().addFieldComment(fieldInnerClass, introspectedTable);
        innerClass.addField(fieldInnerClass);
    }

}
